#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMouseEvent>
#include <QPainter>  //图形绘制库
#include <QMessageBox>  //容纳文字的容器库


// 日出日落底线：底部水平居中，y轴靠下
const QPoint MainWindow::sun[2] = {
    QPoint(10, 60),   // 左端点（y轴下移，贴近控件底部）
    QPoint(110, 60)   // 右端点
};

// 日出日落时间文本框：底线上方，左右分布且居中
const QRect MainWindow::sunRizeSet[2] = {
    QRect(0, 70, 50, 20),   // 左文本框（上移，与底线留空）
    QRect(80, 70, 50, 20)   // 右文本框
};

// 圆弧与标题区域：顶部居中，不与文字/底线重叠
const QRect MainWindow::rect[2] = {
    QRect(20, 20, 80, 80),  // 虚线圆弧区域（控件上半部分居中）
    QRect(40, 70, 40, 20)   // “日出日落”标题文本框（与时间文本框分层）
};


#define SPAN_INDEX 3 // 温度曲线间隔指数
#define ORIGIN_SIZE 3 // 温度曲线原点大小
#define TEMPERATURE_STARTING_COORDINATE 45 // 高温平均值起始坐标


void MainWindow::initWeatherIconMap()
{
    weatherIconMap = {
        {"暴雪", "BaoXue.png"},
        {"暴雨", "BaoYu.png"},
        {"暴雨到大暴雨", "BaoYuDaoDaBaoYu.png"},
        {"大暴雨", "DaBaoYu.png"},
        {"大暴雨到特大暴雨", "DaBaoYuDaoTeDaBaoYu.png"},
        {"大到暴雪", "DaDaoBaoXue.png"},
        {"大到暴雨", "DaDaoBaoYu.png"},
        {"大雪", "DaXue.png"},
        {"大雨", "DaYu.png"},
        {"冻雨", "DongYu.png"},
        {"多云", "DuoYun.png"},
        {"浮尘", "FuChen.png"},
        {"雷阵雨", "LeiZhenYu.png"},
        {"雷阵雨伴有冰雹", "LeiZhenYuBanYouBingBao.png"},
        {"霾", "Mai.png"},
        {"强沙尘暴", "QiangShaChenBao.png"},
        {"晴", "Qing.png"},
        {"沙尘暴", "ShaChenBao.png"},
        {"特大暴雨", "TeDaBaoYu.png"},
        {"无数据", "undefined.png"},
        {"雾", "Wu.png"},
        {"小到中雪", "XiaoDaoZhongXue.png"},
        {"小到中雨", "XiaoDaoZhongYu.png"},
        {"小雪", "XiaoXue.png"},
        {"小雨", "XiaoYu.png"},
        {"雪", "Xue.png"},
        {"扬沙", "YangSha.png"},
        {"阴", "Yin.png"},
        {"雨", "Yu.png"},
        {"雨夹雪", "YuJiaXue.png"},
        {"阵雪", "ZhenXue.png"},
        {"阵雨", "ZhenYu.png"},
        // 新增API中出现的天气类型（如“中雨”）
        {"中雨", "ZhongYu.png"},
        {"中雪", "ZhongXue.png"},
        {"大到中雨", "DaDaoZhongYu.png"},
        {"大到中雪", "DaDaoZhongXue.png"}
    };
}

MainWindow::MainWindow(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MainWindow)
{

    // 新增：初始化天气图标映射表（必须在使用映射表前调用）
    initWeatherIconMap();

    ui->setupUi(this);

    //设置窗口属性为无边框的窗口
    setWindowFlag(Qt::FramelessWindowHint);
    //固定窗口大小
    setFixedSize(width(),height());
    exitMenu = new QMenu(this);
    exitAct = new QAction;
    exitAct->setText(u8"退出");
    exitAct->setIcon(QIcon(":/icon/close.png"));

    //当点击事件触发以后会传进connect里进行处理
    exitMenu->addAction(exitAct);
    connect(exitAct,SIGNAL(triggered(bool)),this,SLOT(slot_exitApp()));

    //UI初始化
    //利用左移运算符，在QLIST类中进行初始化操作、类似于压入栈操作，因为list类一开始为空
    forecast_week_list << ui->week0Lb << ui->week1Lb << ui->week2Lb << ui->week3Lb << ui->week4Lb<<ui->week5Lb;
    forecast_date_list << ui->date0Lb << ui->date1Lb << ui->date2Lb << ui->date3Lb << ui->date4Lb<<ui->date5Lb;
    forecast_aqi_list << ui->quality0Lb << ui->quality1Lb << ui->quality2Lb << ui->quality3Lb << ui->quality4Lb<<ui->quality5Lb;
    forecast_type_list << ui->type0Lb << ui->type1Lb << ui->type2Lb << ui->type3Lb << ui->type4Lb<<ui->type5Lb;
    forecast_typeIco_list << ui->typeico0Lb << ui->typeico1Lb << ui->typeico2Lb << ui->typeico3Lb << ui->typeico4Lb<<ui->typeico5Lb;
    forecast_high_list << ui->high0Lb << ui->high1Lb << ui->high2Lb << ui->high3Lb << ui->high4Lb<<ui->high5Lb;
    forecast_low_list << ui->low0Lb << ui->low1Lb << ui->low2Lb << ui->low3Lb << ui->low4Lb<<ui->low5Lb;

    // dateLb和WeekLb样式表设置；手动设置样式表，好处是可以批量设置，不用在ui文件里挨个点击设置。
    for (int i = 0; i < 6; i++)
    {
        forecast_date_list[i]->setStyleSheet("background-color: rgba(0, 255, 255, 100);");
        forecast_week_list[i]->setStyleSheet("background-color: rgba(0, 255, 255, 100);");
    }

    //设计搜索框圆角样式，设计鼠标移动到搜索框则搜索框边缘变为绿色
    ui->cityLineEdit->setStyleSheet("QLineEdit { border: 1px solid gray; border-radius: 4px; background: rgba(47, 47, 47, 130); } "
                                    "QLineEdit:hover { border-color: rgb(101, 255, 106); }");


    // 新增：初始化forecast数组为默认值
    for (int i = 0; i < 6; i++) {
        forecast[i] = Forecast();
    }

    //网络请求初始化
    // 请求天气API信息
    url = "http://t.weather.itboy.net/api/weather/city/";
    city = u8"西安";
    cityTmp = city;
    manager = new QNetworkAccessManager(this);
    //信号与槽要先绑定好
    connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replayFinished(QNetworkReply*)));
    getWeatherInfo(manager);

    ui->sunRiseSetLb->installEventFilter(this);//为日出日落绘制安装事件过滤器
    ui->curveLb->installEventFilter(this); // 为 curveLb 安装事件过滤器
    ui->cityLineEdit->installEventFilter(this);//编辑框也安装一下


    sunTimer = new QTimer(ui->sunRiseSetLb);
    connect(sunTimer, SIGNAL(timeout()), ui->sunRiseSetLb, SLOT(update()));
    sunTimer->start(1000);  //1秒触发一次

}


void MainWindow::parseJson(QByteArray& bytes)
{
    QJsonParseError err;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(bytes, &err);
    if (err.error != QJsonParseError::NoError) {
        return;
    }

    QJsonObject jsObj = jsonDoc.object();
    QString message = jsObj.value("message").toString();
    if (!message.contains("success")) {
        QMessageBox::information(this, tr("Json解析错误"), u8"天气：城市错误！", QMessageBox::Ok);
        city = cityTmp;
        return;
    }

    // 核心修正：将API根对象传给today，而非dataObj
    today = jsObj; // 匹配上面修改的Today::operator=逻辑

    // 解析昨天数据（forecast[0]）
    QJsonObject dataObj = jsObj.value("data").toObject();
    if (dataObj.contains("yesterday")) {
        forecast[0] = dataObj.value("yesterday").toObject();
    }

    // 解析预报数据（forecast[1]-forecast[5]，取5天，凑齐6天）
    QJsonArray forecastArr = dataObj.value("forecast").toArray();
    int j = 0;
    for (int i = 1; i < 6 && j < forecastArr.size(); i++) {
        forecast[i] = forecastArr.at(j).toObject();
        j++;
    }

    setLabelContent();
}

void MainWindow::setLabelContent()
{
    //更新UI数据
    //今日数据
    ui->dateLb->setText(today.date);
    ui->temLb->setText(today.wendu);
    ui->cityLb->setText(today.city);
    ui->typeLb->setText(today.type);
    ui->noticeLb->setText(today.notice);
    ui->shiduLb->setText(today.shidu);
    ui->pm25Lb->setText(today.pm25);
    ui->FxLb->setText(today.fx);
    ui->FlLb->setText(today.fl);
    ui->ganmaoBrowser->setText(today.ganmao);

    // ---------- 新增：加载当天天气图标 ----------
    QString todayType = today.type;
    QString iconName = weatherIconMap.contains(todayType) ? weatherIconMap[todayType] : "undefined.png";
    QString iconPath = QString(":/images/%1").arg(iconName);
    QPixmap pixmap(iconPath);
    if (!pixmap.isNull()) {
        ui->typeicoLb->setPixmap(pixmap.scaled(ui->typeicoLb->size(),
                                               Qt::KeepAspectRatio,
                                               Qt::SmoothTransformation));
    } else {
        qDebug() << "当天图标加载失败：" << iconPath;
    }

    // 六天数据
    for (int i = 0; i < 6; i++)
    {

        forecast_week_list[i]->setText(forecast[i].week.right(3));
        forecast_date_list[i]->setText(forecast[i].date.left(3));
        forecast_type_list[i]->setText(forecast[i].type);

        //forecast_high_list[i]->setText(forecast[i].high.split("(").at(1));
        //forecast_low_list[i]->setText(forecast[i].low.split("(").at(1));
        // 修正 forecast_high_list（原第133行）
        QStringList highParts = forecast[i].high.split("(");
        QString highText = (highParts.size() > 1) ? highParts[1].remove(")") : forecast[i].high;
        forecast_high_list[i]->setText(highText);
        // 修正 forecast_low_list（原第134行）
        QStringList lowParts = forecast[i].low.split("(");
        QString lowText = (lowParts.size() > 1) ? lowParts[1].remove(")") : forecast[i].low;
        forecast_low_list[i]->setText(lowText);

        //forecast_typeIco_list[i]->setStyleSheet( tr("image: url(:/images/%1.png);").arg(forecast[i].type));
        // 修正天气图标加载
        QString type = forecast[i].type;
        QString iconName = weatherIconMap.contains(type) ? weatherIconMap[type] : "undefined.png";
        QString iconPath = QString(":/images/%1").arg(iconName);
        QPixmap pixmap(iconPath);
        if (!pixmap.isNull()) {
            forecast_typeIco_list[i]->setPixmap(pixmap.scaled(forecast_typeIco_list[i]->size(),
                                                              Qt::KeepAspectRatio,
                                                              Qt::SmoothTransformation));

            QString type = forecast[i].type;
            QString iconName = weatherIconMap.contains(type) ? weatherIconMap[type] : "undefined.png";
            if (iconName == "undefined.png") {
                qDebug() << "未匹配的天气类型：" << type;
            }
        } else {
            qDebug() << "图标加载失败：" << iconPath;
        }


        if (forecast[i].aqi.toInt() >= 0 && forecast[i].aqi.toInt() <= 50)
        {
            forecast_aqi_list[i]->setText(u8"优质");
            forecast_aqi_list[i]->setStyleSheet("color: rgb(0, 255, 0);");
        }
        else if (forecast[i].aqi.toInt() > 50 && forecast[i].aqi.toInt() <= 100)
        {
            forecast_aqi_list[i]->setText(u8"良好");
            forecast_aqi_list[i]->setStyleSheet("color: rgb(255, 255, 0);");
        }
        else if (forecast[i].aqi.toInt() > 100 && forecast[i].aqi.toInt() <= 150)
        {
            forecast_aqi_list[i]->setText(u8"轻度污染");
            forecast_aqi_list[i]->setStyleSheet("color: rgb(255, 170, 0);");
        }
        else if (forecast[i].aqi.toInt() > 150 && forecast[i].aqi.toInt() <= 200)
        {
            forecast_aqi_list[i]->setText(u8"重度污染");
            forecast_aqi_list[i]->setStyleSheet("color: rgb(255, 0, 0);");
        }
        else
        {
            forecast_aqi_list[i]->setText(u8"严重污染");
            forecast_aqi_list[i]->setStyleSheet("color: rgb(170, 0, 0);");
        }
    }
    //设置昨天和今天的星期数
    ui->week0Lb->setText(u8"昨天");
    ui->week1Lb->setText(u8"今天");

    //温度曲线(curveLb)的绘制和日出日落的绘制
    ui->curveLb->update(); // 触发 curveLb 的 Paint 事件

}



//绘制日出日落的函数实现
void MainWindow::paintSunRiseSet()
{
    QPainter painter(ui->sunRiseSetLb);
    // 反锯齿设置
    painter.setRenderHint(QPainter::Antialiasing,true);

    //-------------------------------------------------
    //绘制黄色底线
    painter.save();//保存当前绘制器的状态
    QPen pen = painter.pen();
    pen.setWidthF(0.5);
    pen.setColor(Qt::yellow);
    painter.setPen(pen);
    painter.drawLine(sun[0], sun[1]);
    painter.restore();//重置资源；  save()函数如果后跟end()，则是结束资源的意思


    //-------------------------------------------------
    //黄色底线下加入文字
    painter.save();
    painter.setFont(QFont("Microsoft Yahei", 8, QFont::Normal)); // 字体、大小、正常粗细
    painter.setPen(Qt::white);

    if (today.sunrise != "" && today.sunset != "")
    {
        //在指定区域内绘制文字
        painter.drawText(sunRizeSet[0], Qt::AlignHCenter, today.sunrise);
        painter.drawText(sunRizeSet[1], Qt::AlignHCenter, today.sunset);
    }
    painter.drawText(rect[1], Qt::AlignHCenter, u8"日出日落");//在指定区域绘制文字
    painter.restore();

    //-------------------------------------------------
    // 绘制圆弧
    painter.save();
    pen.setWidthF(0.5);         //设置线条的宽度0.5
    pen.setStyle(Qt::DotLine);  //虚线
    pen.setColor(Qt::green);    //设置颜色
    painter.setPen(pen);
    painter.drawArc(rect[0], 0 * 16, 180 * 16); //绘制圆弧
    painter.restore();

    //-------------------------------------------------
    // 绘制日出日落占比
    // 绘制日出日落占比扇形
    if (!today.sunrise.isEmpty() && !today.sunset.isEmpty()) {
        painter.setPen(Qt::NoPen);
        painter.setBrush(QColor(255, 85, 0, 100));

        int startAngle, spanAngle;
        QString sunsetTime = today.date + " " + today.sunset;
        QDateTime current = QDateTime::currentDateTime();
        QDateTime sunset = QDateTime::fromString(sunsetTime, "yyyy-MM-dd hh:mm");

        if (current > sunset) {
            // 日落之后，扇形占满整个半圆
            startAngle = 0 * 16;
            spanAngle = 180 * 16;
        } else {
            // 计算当天日出、日落的分钟数（从0点开始）
            QStringList riseParts = today.sunrise.split(":");
            QStringList setParts = today.sunset.split(":");
            int riseMin = riseParts[0].toInt() * 60 + riseParts[1].toInt();
            int setMin = setParts[0].toInt() * 60 + setParts[1].toInt();
            int nowMin = QTime::currentTime().hour() * 60 + QTime::currentTime().minute();

            // 计算时间占比（0~1）
            double duration = setMin - riseMin;
            double elapsed = nowMin - riseMin;
            double remaining = setMin - nowMin;

            // 转换为角度（180度对应半圆，*16是Qt角度的缩放系数）
            startAngle = (remaining / duration) * 180 * 16;
            spanAngle = (elapsed / duration) * 180 * 16;

            // 确保角度为非负值
            if (startAngle < 0) startAngle = 0;
            if (spanAngle < 0) spanAngle = 0;
        }

        // 绘制扇形（需确保rect[0]的区域足够容纳）
        if (startAngle >= 0 && spanAngle >= 0) {
            painter.drawPie(rect[0], startAngle, spanAngle);
        }
    }

}


void MainWindow::paintCurve(){
    QPainter painter(ui->curveLb);
    painter.setRenderHint(QPainter::Antialiasing,true);
    int tempTotal = 0;
    int high[6] = {0};
    int low[6] = {0};
    //计算平均值
    QString h, l;
    for (int i = 0; i < 6; i++)
    {
        h = forecast[i].high.split(" ").at(1);
        h = h.left(h.length() - 1);
        high[i] = (int)(h.toDouble());
        tempTotal += high[i];

        l = forecast[i].low.split(" ").at(1);
        l = l.left(l.length() - 1);
        low[i] = (int)(l.toDouble());
    }

    int tempAverage = (int)(tempTotal / 6); // 最高温平均值

    // 算出温度对应坐标
    int pointX[6] = {40, 110, 165, 241, 310, 379}; // 点的 X 坐标
    int pointHY[6] = {0};
    int pointLY[6] = {0};
    for (int i = 0; i < 6; i++)
    {
        pointHY[i] = TEMPERATURE_STARTING_COORDINATE - (high[i] - tempAverage) * SPAN_INDEX;
        pointLY[i] = TEMPERATURE_STARTING_COORDINATE + (tempAverage - low[i]) * SPAN_INDEX;
    }


    QPen pen=painter.pen();
    pen.setWidth(1);
    // 高温曲线绘制
    painter.save();
    //昨天到今天
    pen.setColor(QColor(255, 170, 0));
    pen.setStyle(Qt::DotLine);
    painter.setPen(pen);
    painter.setBrush(QColor(255, 170, 0));
    painter.drawEllipse(QPoint(pointX[0], pointHY[0]), ORIGIN_SIZE, ORIGIN_SIZE);
    painter.drawEllipse(QPoint(pointX[1], pointHY[1]), ORIGIN_SIZE, ORIGIN_SIZE);
    painter.drawLine(pointX[0], pointHY[0], pointX[1], pointHY[1]);
    //今天到未来四天
    pen.setStyle(Qt::SolidLine);
    pen.setWidth(1);
    painter.setPen(pen);

    for (int i = 1; i < 5; i++)
    {
        painter.drawEllipse(QPoint(pointX[i+1], pointHY[i+1]), ORIGIN_SIZE, ORIGIN_SIZE);
        painter.drawLine(pointX[i], pointHY[i], pointX[i+1], pointHY[i+1]);
    }
    painter.restore();

    // 低温曲线绘制
    pen.setColor(QColor(0, 255, 255));
    pen.setStyle(Qt::DotLine);
    painter.setPen(pen);
    painter.setBrush(QColor(0, 255, 255));
    painter.drawEllipse(QPoint(pointX[0], pointLY[0]), ORIGIN_SIZE, ORIGIN_SIZE);
    painter.drawEllipse(QPoint(pointX[1], pointLY[1]), ORIGIN_SIZE, ORIGIN_SIZE);
    painter.drawLine(pointX[0], pointLY[0], pointX[1], pointLY[1]);

    pen.setStyle(Qt::SolidLine);
    pen.setColor(QColor(0, 255, 255));
    painter.setPen(pen);

    for (int i = 1; i < 5; i++)
    {
        painter.drawEllipse(QPoint(pointX[i+1], pointLY[i+1]), ORIGIN_SIZE, ORIGIN_SIZE);
        painter.drawLine(pointX[i], pointLY[i], pointX[i+1], pointLY[i+1]);
    }

}


void MainWindow::replayFinished(QNetworkReply *reply)
{
    /* 获取响应的信息，状态码为200表示正常 */
    QVariant status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    if(reply->error() != QNetworkReply::NoError || status_code != 200)
    {
        QMessageBox::warning(this, u8"错误", u8"天气：请求数据错误，检查网络连接！", QMessageBox::Ok);
        return;
    }

    //收到的应答数据都转换为字节数据
    QByteArray bytes = reply->readAll();
    //qDebug()<<bytes;//在应用程序输出中以字符串进行输出json数据报
    parseJson(bytes);//json解析，回头讲
}


/* 请求数据 */
void MainWindow::getWeatherInfo(QNetworkAccessManager *manager)
{
    QString citycode = tool[city];
    if(citycode=="000000000"){
        QMessageBox::warning(this, u8"错误", u8"天气：指定城市不存在！", QMessageBox::Ok);
        return;
    }
    QUrl jsonUrl(url + citycode);
    manager->get(QNetworkRequest(jsonUrl));
}




MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::contextMenuEvent(QContextMenuEvent *event)
{
    exitMenu->exec(QCursor::pos());
    event->accept();
}

//退出按键事件
void MainWindow::slot_exitApp()
{
    qApp->exit(0);
}

void MainWindow::mousePressEvent(QMouseEvent*event)
{
    //记录两个位置的差值，按下的位置和原窗口位置
    mPos = event->globalPosition().toPoint() - this->pos();

}

void MainWindow::mouseMoveEvent(QMouseEvent*event)
{
    //利用记录的mPos位置的差值，让event坐标向量移动
    move(event->globalPosition().toPoint() - mPos);
}

bool MainWindow::eventFilter(QObject* watched, QEvent* event)
{
    if (watched == ui->sunRiseSetLb && event->type() == QEvent::Paint)
    {
        paintSunRiseSet();// 触发日出日落图像绘制
    }
    else if (watched == ui->curveLb && event->type() == QEvent::Paint)
    {
        paintCurve(); // 触发温度曲线绘制
    }
    return QWidget::eventFilter(watched, event);
}


//刷新按钮
void MainWindow::on_refreshBt_clicked()
{
    getWeatherInfo(manager);
    ui->curveLb->update();//更新温度曲线
}

//搜索按钮
void MainWindow::on_searchBt_clicked()
{
    cityTmp=city;
    city=ui->cityLineEdit->text();
    getWeatherInfo(manager);
}

